#!/usr/bin/ruby
# -*- coding: utf-8 -*-
require "rubygems"
require "opengl"
require "glut"
require "m3g"
require "pp"

# 注意: 回転はクォータニオンで指定するが、
# M3Gで定義されていないQuaternionクラスはRuby側に公開していない。
# 来的にはRubyから使えるようにするかも。
# q0 = M3G::Quaternion.new 0, 0,1,0    = 0,0,0, 1
# q1 = M3G::Quaternion.new 180, 0,1,0  = 0,1,0, 0
# q2 = M3G::Quaternion.new 360, 0,1,0  = 0,0,0, -1


class MyGLUTWidget
  def initialize
    GLUT.Init
    GLUT.InitWindowSize  256, 256
    GLUT.InitDisplayMode GLUT::GLUT_DOUBLE | GLUT::GLUT_RGB | GLUT::GLUT_DEPTH
    GLUT.CreateWindow "Ruby-M3G"

    initialize_scene

    GLUT.ReshapeFunc  method(:reshape).to_proc()
    GLUT.DisplayFunc  method(:display).to_proc()
    GLUT.KeyboardFunc method(:keyboard).to_proc()
    GLUT.MouseFunc    method(:mouse).to_proc()
    GLUT.IdleFunc     method(:idle).to_proc()
  end

  def initialize_scene

    controller_translation = M3G::AnimationController.new
    controller_translation.speed = 1, 0
    controller_orientation = M3G::AnimationController.new
    controller_orientation.speed = 2, 0

    
    keyframe_mesh_translation = M3G::KeyframeSequence.new 4, 3, M3G::KeyframeSequence::LINEAR
    keyframe_mesh_orientation = M3G::KeyframeSequence.new 3, 4, M3G::KeyframeSequence::SLERP
    
    frame_mesh_translation = [[0,0,0], [4,0,0], [-4,0,0]]
    frame_mesh_orientation = [[0,0,0,1], [0,1,0,0], [0,0,0,-1]]
    keyframe_mesh_translation.keyframe[0] = 0,   frame_mesh_translation[0]
    keyframe_mesh_translation.keyframe[1] = 100, frame_mesh_translation[1]
    keyframe_mesh_translation.keyframe[2] = 200, frame_mesh_translation[2]
    keyframe_mesh_translation.keyframe[3] = 300, frame_mesh_translation[0]
    keyframe_mesh_translation.repeat_mode = M3G::KeyframeSequence::LOOP
    keyframe_mesh_translation.valid_range = 0, 3
    keyframe_mesh_translation.duration    = 400
    keyframe_mesh_orientation.keyframe[0] = 0,   frame_mesh_orientation[0]
    keyframe_mesh_orientation.keyframe[1] = 100, frame_mesh_orientation[1]
    keyframe_mesh_orientation.keyframe[2] = 200, frame_mesh_orientation[2]
    keyframe_mesh_orientation.repeat_mode = M3G::KeyframeSequence::LOOP
    keyframe_mesh_orientation.valid_range = 0, 2
    keyframe_mesh_orientation.duration    = 200
    
    animation_mesh_translation = M3G::AnimationTrack.new keyframe_mesh_translation, M3G::AnimationTrack::TRANSLATION
    animation_mesh_translation.controller = controller_translation
    animation_mesh_orientation = M3G::AnimationTrack.new keyframe_mesh_orientation, M3G::AnimationTrack::ORIENTATION
    animation_mesh_orientation.controller = controller_orientation

    bg = M3G::Background.new
    bg.color = 0x7f7f7f7f

    cam = M3G::Camera.new
    cam.look_at 0,0,10, 0,0,0, 0,1,0

    positions = M3G::VertexArray.new 4,3,2
    positions.values[0,4] = [1,-1,0, 1,1,0, -1,-1,0, -1,1,0]
    
    scale = 1
    bias  = [0,0,0]
    vertices = M3G::VertexBuffer.new
    vertices.positions = positions, scale, bias
    
    indices = [0,1,2,3]
    strips  = [4]
    tris = M3G::TriangleStripArray.new indices, strips
    
    mat = M3G::Material.new
    mat.color[M3G::Material::DIFFUSE] = 0x7f0000ff

    pmode = M3G::PolygonMode.new
    pmode.culling = M3G::PolygonMode::CULL_NONE

    app = M3G::Appearance.new
    app.material = mat
    app.polygon_mode = pmode

    mesh = M3G::Mesh.new vertices, tris, app
    mesh.animation_track << animation_mesh_translation
    mesh.animation_track << animation_mesh_orientation
    
    @wld = M3G::World.new
    @wld.child << cam
    @wld.child << mesh
    @wld.active_camera = cam
    @wld.background    = bg

    @world_time = 0
  end

  def reshape width, height
    g3d = M3G::Graphics3D::instance
    g3d.viewport = 0,0,width,height
    @wld.active_camera.perspective = 45, width/(height*1.0), 0.1, 100
  end

  def display
    g3d = M3G::Graphics3D::instance
    g3d.render @wld
    GLUT.SwapBuffers()
  end
  
  def keyboard key, x, y
    if key == 113  # 'q'
      exit
    elsif key == 32 # ' '
      @wld.animate @world_time
      @world_time += 2
    end
    GLUT.PostRedisplay
  end

  def mouse button, state, x, y
  end

  def idle
    GLUT.PostRedisplay
  end

  def start
    GLUT.MainLoop
  end

end


MyGLUTWidget.new.start

